package com.soundplus.app.shp04.Activity;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.ParcelUuid;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.example.sppmode.Common.AllParam;
import com.example.sppmode.Common.PairedDeviceInfo;
import com.soundplus.app.shp04.Common.DeviceListAdapter;
import com.example.sppmode.Common.PairedDevMgr;
import com.soundplus.app.shp04.DeviceConnectMgr.DevConnMgr;
import com.soundplus.app.shp04.R;
import com.soundplus.app.shp04.databinding.ActivityDeviceScanBinding;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;

public class LeDeviceScanActivity extends AppCompatActivity {

    public static final String TAG = "LeDeviceScanActivity";

    private Context context;
    private ActivityDeviceScanBinding binding;

    private DeviceListAdapter deviceListAdapter = null;
    private final List<PairedDeviceInfo> scannedDeviceList = new ArrayList<>();

    private BluetoothAdapter bluetoothAdapter = null;
    private BluetoothLeScanner bluetoothLeScanner = null;
    private MyScanCallback myScanCallback = null;
    private DeviceSortComparator deviceSortComparator = null;
    private DevConnMgr devConnMgr;
    private final String[] whiteList = new String[]{"SEP01", "TMH"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        context = this;
        binding = ActivityDeviceScanBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            Toast.makeText(context, R.string.le_not_support, Toast.LENGTH_SHORT).show();
            return;
        }

        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
        myScanCallback = new MyScanCallback();
        deviceSortComparator = new DeviceSortComparator();
        devConnMgr = DevConnMgr.getInstance();

        initView();
    }

    @Override
    protected void onResume() {
        super.onResume();
        startScanLeDevice();
    }

    @Override
    protected void onPause() {
        super.onPause();
        stopScanLeDevice();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    private void exitDeviceScan() {
        boolean firstRunning = AllParam.getAppInfo().isFirstRunning();
        if (firstRunning) {
            Intent intent = new Intent(LeDeviceScanActivity.this, MainActivity.class);
            startActivity(intent);
        }

        LeDeviceScanActivity.this.finish();
    }


    private void initView() {
        scannedDeviceList.clear();

        deviceListAdapter = new DeviceListAdapter(context, scannedDeviceList);
        binding.lvScannedDevice.setAdapter(deviceListAdapter);
        binding.lvScannedDevice.setOnItemClickListener((adapterView, view, i, l) -> {
            stopScanLeDevice();
            addPairedDevice(scannedDeviceList.get(i));
            devConnMgr.disconnectDevice();
        });

        binding.btnRescan.setOnClickListener(view -> {
            scannedDeviceList.clear();
            deviceListAdapter.notifyDataSetChanged();
            stopScanLeDevice();
            startScanLeDevice();
        });
    }

    private class MyScanCallback extends ScanCallback {
        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            super.onBatchScanResults(results);
            for (ScanResult result : results) {
                dealScanResult(result);
            }
        }

        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
            stopScanLeDevice();
        }

        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            dealScanResult(result);
        }
    }

    @SuppressLint("MissingPermission")
    private void startScanLeDevice() {
        bluetoothLeScanner.startScan(myScanCallback);
        binding.tvScanPrompt.setVisibility(View.VISIBLE);
    }

    @SuppressLint("MissingPermission")
    private void stopScanLeDevice() {
        binding.tvScanPrompt.setVisibility(View.INVISIBLE);
        bluetoothLeScanner.stopScan(myScanCallback);
    }

    private static final UUID BLE_SERVICE_UUID = UUID.fromString("50530001-0000-1000-8000-00805F9B34FB");

    @SuppressLint("MissingPermission")
    private void dealScanResult(ScanResult result) {
        boolean deviceValid = false;
        boolean deviceExsit = false;
        int deviceType = PairedDeviceInfo.DEVICE_TYPE_COMMON;



        ScanRecord scanRecord = result.getScanRecord();
//        byte[] data = scanRecord.getBytes();
//        if (true) {//if (data[5] == 0x01) {
//            deviceType = PairedDeviceInfo.DEVICE_TYPE_HEARAID;
//        }

        Log.d(TAG, "dealScanResult devName:"+ result.getDevice().getName());
        if (result.getDevice().getName() == null) {
            Log.d(TAG, "dealScanResult return name ==  null");
            return;
        }

        Log.d(TAG, "BLE_SERVICE_UUID:"+ BLE_SERVICE_UUID);

        List<ParcelUuid> parcelUuidList = scanRecord.getServiceUuids();
        if (parcelUuidList != null) {
            for (ParcelUuid parcelUuid : parcelUuidList) {
                if(parcelUuid != null) {
                    Log.d(TAG, "parcelUuid:" + parcelUuid.getUuid());
                    if (parcelUuid.getUuid().compareTo(BLE_SERVICE_UUID) == 0) {
                        deviceValid = true;
                    }
                }
            }
        }

        if (deviceValid == false) {
            for (String str : whiteList) {
                if (str != null) {
                    if (result.getDevice().getName().startsWith(str)) {
                        deviceValid = true;
                        deviceType = PairedDeviceInfo.DEVICE_TYPE_COMMON;
                        break;
                    }
                }
            }
        }

        if (!deviceValid) {
            Log.d(TAG, "dealScanResult return ivalid device");
            return;
        }

        for (PairedDeviceInfo pairedDeviceInfo : scannedDeviceList) {
            if (pairedDeviceInfo.getMacAddr().equals(result.getDevice().getAddress())) {
                deviceExsit = true;
                pairedDeviceInfo.setRssi(result.getRssi());
                break;
            }
        }

        if (!deviceExsit) {
            PairedDeviceInfo pairedDeviceInfo = new PairedDeviceInfo();
            pairedDeviceInfo.setDevType(deviceType);
            if (result.getDevice().getName() == null)
                pairedDeviceInfo.setName("Unknown");
            else
                pairedDeviceInfo.setName(result.getDevice().getName());
            pairedDeviceInfo.setMacAddr(result.getDevice().getAddress());
            pairedDeviceInfo.setRssi(result.getRssi());
            scannedDeviceList.add(pairedDeviceInfo);
            Collections.sort(scannedDeviceList, deviceSortComparator);
            deviceListAdapter.notifyDataSetChanged();
        }

    }

    private void addPairedDevice(PairedDeviceInfo pairedDeviceInfo) {
        PairedDevMgr pairedDevInfo = AllParam.getPairedDevInfo();
        pairedDevInfo.addDevice(pairedDeviceInfo);
        pairedDevInfo.updateLastConnDevInfo(pairedDeviceInfo, true);
        exitDeviceScan();
    }

    class DeviceSortComparator implements Comparator {

        @Override
        public int compare(Object object1, Object object2) {
            PairedDeviceInfo pairedDeviceInfo1 = (PairedDeviceInfo) object1;
            PairedDeviceInfo pairedDeviceInfo2 = (PairedDeviceInfo) object2;
            int rssi1 = pairedDeviceInfo1.getRssi();
            int rssi2 = pairedDeviceInfo2.getRssi();

            if (rssi1 < rssi2)
                return 1;
            else if (rssi1 > rssi2)
                return -1;
            return 0;
        }
    }

}
